package com.puzzlebazar.client.hashiwokakero;

import com.puzzlebazar.client.util.Vec2i;

public class Bridge {

	private int value;
	private Island connections[] = new Island[2];


	/**
	 * Creates a new Hashiwokakero bridge having the given value
	 * 
	 * @param value The value for the bridge (the number of lanes of this bridge)
	 */
	public Bridge(int value) {
		this.value = value;
	}	
	

	/**
	 * Disconnect the bridge from all attached islands
	 * 
	 * @throws Exception
	 */
	public void disconnect() throws Exception {
		if ( connections[0] != null ) connections[0].disconnectFromBridge( this );
		if ( connections[1] != null ) connections[1].disconnectFromBridge( this );
		assert connections[0] == null && connections[1] == null;
	}

	
	/**
	 * <p>Connects one end of the bridge to the specified island</p>
	 * 
	 * <p><strong>*** Should only be called by Island ***</strong>
	 * Call island.connectToBridge instead.</p>
	 * 
	 * @param island  Island to connect to the bridge
	 * @throws Exception
	 */
	public void connectTo(Island island) throws Exception {
		if( connections[0] == null ) {
			connections[0] = island;
		}
		else if( connections[1] == null ) {
			connections[1] = island;
		}
		else {
			throw new Exception( "Bridge already connected" );
		}
	}

	/**
	 * <p>Disconnect the bridge from the specified island.</p>
	 * 
	 * <p><strong>*** Should only be called by Island ***</strong> 
	 * Call island.disconnectFromBridge instead.</p>
	 * 
	 * @param island  Island to disconnect from the bridge
	 * @throws Exception
	 */
	public void disconnectFrom(Island island) throws Exception {
		if( connections[0] == island ) {
			connections[0] = null;
		}
		else if( connections[1] == island ) {
			connections[1] = null;
		}
		else {
			throw new Exception( "No island to disconnect" );
		}
		
	}

	/**
	 * @return The value of the bridge
	 */
	public int getValue() {
		return value;
	}

	/**
	 * @param i The end of the bridge to access (0 or 1)
	 * @return The island to which this end of the bridge is connected
	 */
	public Island getConnection( int i ) throws Exception {
		if( i < 0 || i >= 2 ) throw new Exception( "Invalid connection end" );		
		return connections[i];
	}


	/**
	 * Access the other end of the bridge given one end
	 * 
	 * @param island The island at one end of the bridge
	 * @return The island at the other end of the bridge
	 * @throws Exception
	 */
	public Island getOtherIsland(Island island) throws Exception {
		if( island == connections[0] ) return connections[1];
		if( island == connections[1] ) return connections[0];
		throw new Exception( "Island not connected, cannot get other island" );
	}

	
	/**
	 * Check if bridge is connected to an island
	 * 
	 * @param island Island to check for connection
	 * @return True if bridge is connected to this island
	 */
	public boolean connectedTo(Island island) {
		if( island == null ) return false;
		return ( connections[0] == island || connections[1] == island );
	}


	/**
	 * Get the location of one end of the bridge
	 * 
	 * @param i
	 * @return
	 */
	public Vec2i getLoc(int i) throws Exception {
		if( i < 0 || i >= 2 ) throw new Exception( "Invalid connection end" );		
		return connections[i].getLoc();
	}

}
